// 导入React核心hooks和组件
import React, { useState, useCallback, useEffect } from "react"
// 导入Ant Design UI组件库中的表单、按钮、卡片等组件
import {
  Form,
  Button,
  Card,
  Typography,
  Input,
  Select,
  InputNumber,
} from "antd"
// 导入自定义的类型定义，包含表单架构、表单数据、表单字段的类型
import type { FormSchema, FormData, FormField } from "../types/schema"

// 从Typography组件中解构出标题和段落组件
const { Title, Paragraph } = Typography
// 从Input组件中解构出文本域组件
const { TextArea } = Input
// 从Select组件中解构出选项组件
const { Option } = Select

// 定义DynamicForm组件的props接口
interface DynamicFormProps {
  schema: FormSchema // 表单的JSON架构定义
  initialValues?: FormData // 可选的初始表单值
  onSubmit?: (values: FormData) => void // 可选的表单提交回调函数
  onValuesChange?: (changedValues: FormData, allValues: FormData) => void // 可选的表单值变化回调函数
  slots?: Record<string, () => React.ReactNode> // 可选的插槽映射，用于自定义内容渲染
}

// 定义并导出DynamicForm函数组件
const DynamicForm: React.FC<DynamicFormProps> = ({
  schema, // 解构传入的表单架构
  initialValues = {}, // 解构传入的初始值，默认为空对象
  onSubmit, // 解构传入的提交回调
  onValuesChange, // 解构传入的值变化回调
  slots = {}, // 解构传入的插槽映射，默认为空对象
}) => {
  // 使用Ant Design的Form.useForm钩子创建表单实例
  const [form] = Form.useForm()
  // 使用useState管理组件内部的表单数据状态，初始化为传入的初始值
  const [formData, setFormData] = useState<FormData>(initialValues)

  // 使用useCallback创建表单值变化处理函数，避免不必要的重新渲染
  // 当表单数据变化时，更新内部state，用于触发字段联动逻辑
  const handleValuesChange = useCallback(
    (changedValues: FormData, allValues: FormData) => {
      setFormData(allValues) // 更新内部状态
      onValuesChange?.(changedValues, allValues) // 调用外部传入的回调函数（如果存在）
    },
    [onValuesChange]
  ) // 依赖项为onValuesChange，当它变化时重新创建函数

  // 使用useCallback创建字段可见性判断函数
  // 根据visibility规则判断字段是否应该显示
  const isFieldVisible = useCallback(
    (field: FormField): boolean => {
      // 如果字段没有可见性规则，默认显示
      if (!field.visibility) {
        return true
      }

      // 解构可见性规则中的关键字段
      const { key, value, operator = "eq" } = field.visibility
      // 获取当前表单中对应字段的值
      const currentValue = formData[key]

      // 根据操作符进行不同的比较逻辑
      switch (operator) {
        case "eq": // 等于
          return currentValue === value
        case "ne": // 不等于
          return currentValue !== value
        case "gt": // 大于（仅适用于数字类型）
          return (
            typeof currentValue === "number" &&
            typeof value === "number" &&
            currentValue > value
          )
        case "lt": // 小于（仅适用于数字类型）
          return (
            typeof currentValue === "number" &&
            typeof value === "number" &&
            currentValue < value
          )
        case "in": // 包含在数组中
          return Array.isArray(value) && value.includes(currentValue)
        default: // 默认情况显示字段
          return true
      }
    },
    [formData]
  ) // 依赖项为formData，当表单数据变化时重新创建函数

  // 使用useCallback创建组件渲染函数
  // 根据字段配置渲染对应的表单组件
  const renderComponent = useCallback(
    (field: FormField) => {
      // 从字段UI配置中解构出组件相关属性（使用any类型避免严格类型检查）
      const {
        component,
        placeholder,
        disabled,
        size,
        options,
        rows,
        slotName,
      } = field.ui as any

      // 根据组件类型进行不同的渲染逻辑
      switch (component) {
        case "Input": // 输入框组件
          return (
            <Input
              placeholder={placeholder} // 占位符文本
              disabled={disabled} // 是否禁用
              size={size} // 组件尺寸
            />
          )

        case "TextArea": // 文本域组件
          return (
            <TextArea
              placeholder={placeholder} // 占位符文本
              disabled={disabled} // 是否禁用
              rows={rows || 4} // 行数，默认4行
            />
          )

        case "Select": // 选择器组件
          return (
            <Select
              placeholder={placeholder} // 占位符文本
              disabled={disabled} // 是否禁用
              size={size} // 组件尺寸
              style={{ width: "100%" }} // 样式设置为全宽
            >
              {/* 遍历选项数组，渲染每个选项 */}
              {options?.map((option: any) => (
                <Option key={option.value} value={option.value}>
                  {option.label}
                </Option>
              ))}
            </Select>
          )

        case "InputNumber": // 数字输入框组件
          return (
            <InputNumber
              placeholder={placeholder} // 占位符文本
              disabled={disabled} // 是否禁用
              size={size} // 组件尺寸
              style={{ width: "100%" }} // 样式设置为全宽
            />
          )

        case "Slot": // 插槽组件，用于渲染自定义内容
          // 检查插槽名称是否存在且对应的插槽函数是否为函数类型
          if (slotName && typeof slots[slotName] === "function") {
            return slots[slotName]() || null // 调用插槽函数并渲染结果
          }
          return null // 如果插槽不存在则返回null

        default: // 默认情况，未支持的组件类型
          console.warn(`未支持的组件类型: ${component}`) // 在控制台输出警告
          return (
            <Input
              placeholder={placeholder} // 默认渲染为普通输入框
              disabled={disabled}
              size={size}
            />
          )
      }
    },
    [slots]
  ) // 依赖项为slots，当插槽映射变化时重新创建函数

  // 使用useCallback创建字段渲染函数
  // 渲染完整的表单字段，包括标签、验证规则等
  const renderField = useCallback(
    (field: FormField) => {
      // 首先检查字段是否应该显示
      if (!isFieldVisible(field)) {
        return null // 如果不可见则返回null
      }

      // 特殊处理Slot类型字段，直接渲染插槽内容，不包裹Form.Item
      if ((field.ui as any).component === "Slot") {
        return (
          <div key={field.key} style={{ margin: "12px 0" }}>
            {renderComponent(field)}
          </div>
        )
      }

      // 普通字段使用Form.Item包裹
      return (
        <Form.Item
          key={field.key} // React列表渲染的唯一key
          name={field.key} // 表单字段名称
          label={field.ui.label} // 字段标签
          // 将自定义验证规则转换为Ant Design表单验证规则格式
          rules={field.rules?.map((rule) => ({
            required: rule.required, // 是否必填
            message: rule.message, // 错误提示信息
            min: rule.minLength || rule.min, // 最小值或最小长度
            max: rule.maxLength || rule.max, // 最大值或最大长度
            pattern: rule.pattern ? new RegExp(rule.pattern) : undefined, // 正则表达式验证
          }))}
        >
          {renderComponent(field)} {/* 渲染实际的表单组件 */}
        </Form.Item>
      )
    },
    [isFieldVisible, renderComponent]
  ) // 依赖项为字段可见性判断函数和组件渲染函数

  // 使用useCallback创建表单提交成功处理函数
  const handleFinish = useCallback(
    (values: FormData) => {
      console.log("表单提交成功:", values) // 在控制台输出提交的数据
      onSubmit?.(values) // 调用外部传入的提交回调函数（如果存在）
    },
    [onSubmit]
  ) // 依赖项为onSubmit回调

  // 使用useCallback创建表单提交失败处理函数
  const handleFinishFailed = useCallback((errorInfo: unknown) => {
    console.log("表单提交失败:", errorInfo) // 在控制台输出错误信息
  }, []) // 无依赖项，函数内容不会变化

  // 使用useEffect处理初始值设置的副作用
  // 当组件挂载或初始值变化时设置表单初始值
  useEffect(() => {
    // 检查初始值是否存在且不为空
    if (initialValues && Object.keys(initialValues).length > 0) {
      form.setFieldsValue(initialValues) // 设置表单字段值
      setFormData(initialValues) // 更新内部状态
    }
  }, [form, initialValues]) // 依赖项为表单实例和初始值

  // 组件的JSX渲染部分
  return (
    <Card>
      {" "}
      {/* 使用Card组件包裹整个表单 */}
      {/* 渲染表单标题 */}
      <Title level={3}>{schema.formName}</Title>
      {/* 如果存在描述信息则渲染描述段落 */}
      {schema.description && <Paragraph>{schema.description}</Paragraph>}
      {/* Ant Design表单组件 */}
      <Form
        form={form} // 表单实例
        layout={schema.layout || "vertical"} // 表单布局，默认为垂直布局
        onFinish={handleFinish} // 提交成功回调
        onFinishFailed={handleFinishFailed} // 提交失败回调
        onValuesChange={handleValuesChange} // 值变化回调
        initialValues={initialValues} // 初始值
      >
        {/* 遍历架构中的字段数组，渲染每个字段 */}
        {schema.fields.map(renderField)}

        {/* 提交按钮 */}
        <Form.Item>
          <Button type="primary" htmlType="submit" size="large">
            {schema.submitText || "提交"}{" "}
            {/* 按钮文本，使用架构中定义的文本或默认文本 */}
          </Button>
        </Form.Item>
      </Form>
    </Card>
  )
}

// 导出组件供其他模块使用
export default DynamicForm
